package com.tp.config;

import com.alibaba.druid.filter.stat.StatFilter;
import com.alibaba.druid.util.JdbcConstants;
import com.alibaba.druid.wall.WallFilter;
import com.jfinal.config.Constants;
import com.jfinal.config.Handlers;
import com.jfinal.config.Interceptors;
import com.jfinal.config.JFinalConfig;
import com.jfinal.config.Plugins;
import com.jfinal.config.Routes;
import com.jfinal.ext.interceptor.SessionInViewInterceptor;
import com.jfinal.ext.route.AutoBindRoutes;
import com.jfinal.kit.Prop;
import com.jfinal.kit.PropKit;
import com.jfinal.log.Log4jLogFactory;
import com.jfinal.plugin.activerecord.ActiveRecordPlugin;
import com.jfinal.plugin.activerecord.CaseInsensitiveContainerFactory;
import com.jfinal.plugin.activerecord.dialect.MysqlDialect;
import com.jfinal.plugin.activerecord.dialect.OracleDialect;
import com.jfinal.plugin.activerecord.dialect.PostgreSqlDialect;
import com.jfinal.plugin.activerecord.tx.TxByMethodRegex;
import com.jfinal.plugin.cron4j.Cron4jPlugin;
import com.jfinal.plugin.druid.DruidPlugin;
import com.jfinal.plugin.druid.DruidStatViewHandler;
import com.jfinal.plugin.ehcache.EhCachePlugin;
import com.jfinal.server.undertow.UndertowServer;
import com.jfinal.template.Engine;
import com.tp.interceptor.CommonInterceptor;
import com.tp.interceptor.UserInterceptor;
import com.tp.interceptor.ExceptionInterceptor;
import com.tp.base.BaseController;
import com.tp.handler.BasePathHandler;
import com.tp.handler.URLOptimizeHandler;
import com.tp.handler.XssHandler;
import com.tp.model._MappingKit;

/**
 * API 引导式配置
 */
public class SysConfig extends JFinalConfig {
	
	static Prop p;
	
	public static String baseUploadPath;
	
	/**
	 * 启动入口，运行此 main 方法可以启动项目，此 main 方法可以放置在任意的 Class 类定义中，不一定要放于此
	 */
	public static void main(String[] args) {
		UndertowServer.start(SysConfig.class);
	}
	
	/**
	 * PropKit.useFirstFound(...) 使用参数中从左到右最先被找到的配置文件
	 * 从左到右依次去找配置，找到则立即加载并立即返回，后续配置将被忽略
	 */
	static void loadConfig() {
		if (p == null) {
			p = PropKit.useFirstFound("config-pro.txt", "config-dev.txt");
		}
	}
	
	private boolean isDevMode() {
		loadConfig();
		return p.getBoolean("devMode", false);
	}
	
	/**
	 * 配置常量
	 */
	public void configConstant(Constants me) {
		loadConfig();
		me.setDevMode(isDevMode());
		me.setLogFactory(new Log4jLogFactory());
		/**
		 * 支持 Controller、Interceptor、Validator 之中使用 @Inject 注入业务层，并且自动实现 AOP
		 * 注入动作支持任意深度并自动处理循环注入
		 */
		me.setInjectDependency(true);
		// 配置对超类中的属性进行注入
		me.setInjectSuperClass(true);
		me.setError404View("/pages/error/404.html");
		me.setError500View("/pages/error/500.html");
		me.setBaseUploadPath("upload");
		baseUploadPath = me.getBaseUploadPath();
	}
	
	/**
	 * 配置路由
	 */
	@SuppressWarnings("unchecked")
	public void configRoute(Routes me) {
		// 新增自动路由
		AutoBindRoutes abr = new AutoBindRoutes();
		abr.setBaseViewPath("/pages");
		abr.addExcludeClasses(BaseController.class);
		me.add(abr);
	}
	
	/**
	 * 配置模板文件
	 */
	public void configEngine(Engine me) {
		// devMode 配置为 true，将支持模板实时热加载
		me.setDevMode(isDevMode());
		// 添加共享函数,等效于在每个页面中添加#include("layout.html")
		me.addSharedFunction("/pages/includes/_head.html");
		me.addSharedFunction("/pages/includes/_layui.html");
		// 分享静态方法
		// me.addSharedStaticMethod(Share.class);
		// 分享所有方法
		// me.addSharedMethod(Share.class);
		// me.addSharedMethod(new Share());
	}
	
	/**
	 * 配置插件
	 */
	public void configPlugin(Plugins me) {
		// 配置 druid 数据库连接池插件
		loadConfig();
		String db_type = p.get("db_type") + ".";
		String jdbcUrl = p.get(db_type + "jdbcUrl");
		String user = p.get(db_type + "user");
		String password = p.get(db_type + "password").trim();
		String driverClass = p.get(db_type + "driverClass");
		
		// 配置数据库连接池插件
		DruidPlugin druidPlugin = new DruidPlugin(jdbcUrl, user, password, driverClass);
		druidPlugin.setInitialSize(5);
		druidPlugin.setMinIdle(5);
		druidPlugin.setMaxActive(20);
		druidPlugin.setMaxWait(60000);
		druidPlugin.setTimeBetweenEvictionRunsMillis(60000);
		druidPlugin.setValidationQuery("SELECT 'x'");
		druidPlugin.setTestWhileIdle(true);
		druidPlugin.setTestOnBorrow(false);
		druidPlugin.setTestOnReturn(false);
		druidPlugin.setMaxPoolPreparedStatementPerConnectionSize(20);
		druidPlugin.setFilters("wall,stat");
		
		// 配置druid的监控
		druidPlugin.addFilter(new StatFilter());
		WallFilter wall = new WallFilter();
		// 设计数据库类型
		if (db_type.startsWith("postgre")) {
			wall.setDbType(JdbcConstants.POSTGRESQL);
		} else if (db_type.startsWith("oracle")) {
			wall.setDbType(JdbcConstants.ORACLE);
		}else if (db_type.startsWith("mysql")) {
			wall.setDbType(JdbcConstants.MYSQL);
		}
		druidPlugin.addFilter(wall);
		me.add(druidPlugin);
		
		// 配置ActiveRecord插件
		ActiveRecordPlugin arp = new ActiveRecordPlugin(druidPlugin);
		// 数据库类型
		if (db_type.startsWith("postgre")) {
			arp.setDialect(new PostgreSqlDialect());
		} else if (db_type.startsWith("oracle")) {
			arp.setDialect(new OracleDialect());
			arp.setContainerFactory(new CaseInsensitiveContainerFactory(true));
		}else if (db_type.startsWith("mysql")) {
			arp.setDialect(new MysqlDialect());
		}
		// 配置显示查询sql语句
		if (isDevMode()) {
			arp.setShowSql(true);
		}
		// 所有映射在 MappingKit 中自动化搞定
		_MappingKit.mapping(arp);
		me.add(arp);
		// 配置缓存插件
		me.add(new EhCachePlugin());
		// 配置定时任务插件
		me.add(new Cron4jPlugin(PropKit.use("task.properties"), "cron4j"));
	}
	
	public static DruidPlugin createDruidPlugin() {
		loadConfig();
		String db_type = p.get("db_type") + ".";
		String jdbcUrl = p.get(db_type + "jdbcUrl");
		String user = p.get(db_type + "user");
		String password = p.get(db_type + "password").trim();
		String driverClass = p.get(db_type + "driverClass");
		
		DruidPlugin dp = new DruidPlugin(jdbcUrl, user, password, driverClass);
		dp.setInitialSize(5);
		dp.setMinIdle(5);
		dp.setMaxActive(20);
		dp.setMaxWait(60000);
		dp.setTimeBetweenEvictionRunsMillis(60000);
		dp.setValidationQuery("SELECT 'x'");
		dp.setTestWhileIdle(true);
		dp.setTestOnBorrow(false);
		dp.setTestOnReturn(false);
		dp.setMaxPoolPreparedStatementPerConnectionSize(20);
		dp.setFilters("wall,stat");
		return dp;
	}
	
	/**
	 * 配置全局拦截器
	 */
	public void configInterceptor(Interceptors me) {
		// 路由拦截器
		//me.add(new RouteInterceptor());
		// 异常拦截器，跳转到500页面
		me.add(new ExceptionInterceptor());
		// Session拦截器
		me.add(new SessionInViewInterceptor());
		// 用户认证
		me.add(new UserInterceptor());
		// 公共属性
		me.add(new CommonInterceptor());
		//配置事务拦截器
		me.add(new TxByMethodRegex("(.*save.*|.*update.*|.*delete.*)"));
	}
	
	/**
	 * 配置处理器
	 */
	public void configHandler(Handlers me) {
		loadConfig();
		// 全路径获取
		me.add(new BasePathHandler("BASE_PATH"));
		me.add(new URLOptimizeHandler());
		me.add(new XssHandler("")); // `/admin*`为排除的目录
		DruidStatViewHandler dvh = new DruidStatViewHandler("/druid");
		me.add(dvh);
	}
}
